#pragma once
#include "cgzITask.h"
#include <clickhouse/client.h>
#include <clickhouse/block.h>
#include <clickhouse/types/types.h>

enum class cgzClickHouseCode
{
    AUTH_SUCCESS, // 认证成功
    EXEC_REQUEST, // 执行请求
    EXEC_REPLY,   // 执行回复
};

enum class cgzClickHouseCmd
{
    INSERT,
    INSERT_BLOCK,
    UPDATE,
    DELETE,
    SELECT,
    CREATE,
    DROP,
    ALTER,
    TRUNCATE,
    EXPLAIN,
    SHOW,
    USE,
};

class cgzClickHouseReply : public cgzIData
{
public:
    cgzClickHouseReply(cgzClickHouseCode code);
    virtual ~cgzClickHouseReply();

public:
    cgzClickHouseCode m_code;
};

// 执行基类
class cgzClickHouseExec : public cgzClickHouseReply
{
public:
    cgzClickHouseExec(const cgzClickHouseCmd cmd, const int cookid = -1);
    virtual ~cgzClickHouseExec();

public:
    cgzClickHouseCmd m_cmd; // 执行类型
    long m_cookid;          // 回调凭证
    bool m_ret;             // 是否回调
    bool m_err;             // 释放错误
};

// 插入block
class cgzClickHouseInsertBlock : public cgzClickHouseExec
{
public:
    cgzClickHouseInsertBlock(
        const char *tbname,
        std::unique_ptr<clickhouse::Block>&& block,
        const long cookid = -1);
    virtual ~cgzClickHouseInsertBlock();

public:
    // 插入数据
    std::string m_tbname;
    std::unique_ptr<clickhouse::Block> m_block;
};

// 插入
class cgzClickHouseInsert : public cgzClickHouseExec
{
public:
    cgzClickHouseInsert(const char *sql, const int cookid = -1);
    virtual ~cgzClickHouseInsert();

public:
    // 更新语句
    std::string m_sql;
};

// 更新
class cgzClickHouseUpdate : public cgzClickHouseExec
{
public:
    cgzClickHouseUpdate(const char *sql, const int cookid = -1);
    virtual ~cgzClickHouseUpdate();

public:
    // 更新语句
    std::string m_sql;
};


// 删除
class cgzClickHouseDelete : public cgzClickHouseExec
{
public:
    cgzClickHouseDelete(const char *sql, const int cookid = -1);
    virtual ~cgzClickHouseDelete();

public:
    // 删除语句
    std::string m_sql;
};

// 查询
class cgzClickHouseSelect : public cgzClickHouseExec
{
public:
    cgzClickHouseSelect(const char *sql, const int cookid = -1);
    virtual ~cgzClickHouseSelect();

public:
    // 查询语句
    std::string m_sql;
    // 查询结果
    std::unique_ptr<clickhouse::Block> m_block;
};

// 建库/建表/视图
class cgzClickHouseCreate : public cgzClickHouseExec
{
public:
    cgzClickHouseCreate(const char *sql, const int cookid = -1);
    virtual ~cgzClickHouseCreate();

public:
    // 创建语句
    std::string m_sql;
};

// 删库/删表/
class cgzClickHouseDrop : public cgzClickHouseExec
{
public:
    cgzClickHouseDrop(const char *sql, const int cookid = -1);
    virtual ~cgzClickHouseDrop();

public:
    // 删除语句
    std::string m_sql;
};

// 修改
class cgzClickHouseAlter : public cgzClickHouseExec
{
public:
    cgzClickHouseAlter(const char *sql, const int cookid = -1);
    virtual ~cgzClickHouseAlter();

public:
    // 修改语句
    std::string m_sql;
};

// 截断
class cgzClickHouseTruncate : public cgzClickHouseExec
{
public:
    cgzClickHouseTruncate(const char *sql, const int cookid = -1);
    virtual ~cgzClickHouseTruncate();

public:
    // 修改语句
    std::string m_sql;
};

// 计划
class cgzClickHouseExplain : public cgzClickHouseSelect
{
public:
    cgzClickHouseExplain(const char *sql, const int cookid = -1);
    virtual ~cgzClickHouseExplain();
};

// 显示
class cgzClickHouseShow : public cgzClickHouseSelect
{
public:
    cgzClickHouseShow(const char *sql, const int cookid = -1);
    virtual ~cgzClickHouseShow();

};

// 切换
class cgzClickHouseUse : public cgzClickHouseExec
{
public:
    cgzClickHouseUse(const char *sql, const int cookid = -1);
    virtual ~cgzClickHouseUse();

public:
    // 切换语句
    std::string m_sql;
};

class cgzClickHouse : public cgzITask
{
public:
    cgzClickHouse(
        cgzCThreadPool *pool,
        const char *name,
        const char *ip,
        const char *user,
        const char *password,
        const int port,
        const char *db,
        const int cid);
    virtual ~cgzClickHouse();

public:
    bool run(int64_t nms) override;
    bool addTask(cgzIData *) override;

public:
    void authret();
    bool connect();
    bool rconnect();
    

protected:
    std::string m_ip;
    std::string m_user;
    std::string m_password;
    std::string m_db;
    std::string m_charset;
    bool m_firstAuth;
    bool m_ping;
    int m_port;
    int m_cid;
    int m_fd;

private:
    std::unique_ptr<clickhouse::Client> m_client;
};
